require("imlua")
require("iuplua")
require("iupluaimglib")
require("iupluaim")
require("cdlua")
require("cdluaim")
require("iupluacd")


--********************************** Images *****************************************


function load_image_PaintLine()
  local PaintLine = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 12, 0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 239, 0, 0, 0, 60, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 227, 0, 0, 0, 8, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 16, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintLine
end

function load_image_PaintPointer()
  local PaintPointer = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 162, 180, 203, 84, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 162, 180, 203, 255, 162, 180, 203, 84, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 240, 243, 246, 255, 162, 180, 203, 255, 162, 180, 203, 69, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 162, 180, 203, 255, 255, 255, 255, 255, 241, 244, 247, 255, 161, 179, 202, 255, 161, 179, 202, 57, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 158, 176, 200, 255, 255, 255, 255, 255, 255, 255, 255, 255, 240, 242, 246, 255, 147, 165, 189, 255, 134, 152, 176, 57, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 153, 172, 195, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 227, 231, 236, 255, 129, 147, 171, 255, 115, 134, 158, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 148, 166, 189, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 253, 253, 254, 255, 213, 218, 226, 255, 111, 130, 154, 255, 96, 115, 140, 57, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 141, 159, 183, 255, 254, 255, 255, 255, 252, 253, 254, 255, 250, 251, 253, 255, 247, 248, 251, 255, 243, 246, 250, 255, 206, 213, 223, 255, 91, 110, 136, 255, 73, 92, 118, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 134, 152, 176, 255, 249, 250, 252, 255, 246, 247, 251, 255, 242, 245, 249, 255, 238, 242, 247, 255, 92, 111, 137, 255, 56, 76, 102, 255, 60, 80, 106, 255, 73, 92, 118, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 127, 145, 170, 255, 241, 244, 249, 255, 205, 212, 221, 255, 88, 108, 133, 255, 229, 234, 243, 255, 105, 124, 148, 255, 105, 124, 148, 83, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 119, 138, 163, 255, 203, 209, 220, 255, 63, 83, 109, 255, 102, 121, 145, 255, 197, 206, 221, 255, 187, 197, 214, 255, 89, 108, 133, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 112, 131, 156, 255, 82, 101, 127, 255, 55, 75, 101, 81, 102, 121, 145, 123, 102, 121, 145, 255, 206, 215, 233, 255, 79, 99, 124, 255, 79, 99, 124, 45, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 105, 124, 150, 255, 255, 255, 255, 0, 255, 255, 255, 0, 102, 121, 145, 18, 95, 115, 140, 255, 190, 202, 223, 255, 152, 167, 189, 255, 67, 87, 112, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 95, 115, 140, 150, 84, 104, 129, 255, 164, 178, 202, 255, 58, 78, 104, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 95, 115, 140, 6, 70, 90, 116, 255, 59, 79, 105, 255, 55, 75, 101, 87, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintPointer
end

function load_image_PaintPencil()
  local PaintPencil = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 194, 126, 104, 73, 173, 108, 94, 255, 173, 108, 94, 255, 188, 121, 101, 48, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 173, 108, 94, 255, 235, 159, 129, 255, 208, 118, 94, 255, 173, 108, 94, 255, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 187, 176, 125, 255, 172, 184, 202, 255, 209, 133, 115, 255, 173, 108, 94, 255, 144, 53, 53, 255, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 185, 172, 115, 255, 238, 224, 140, 255, 217, 196, 108, 255, 134, 134, 125, 255, 144, 53, 53, 255, 131, 57, 47, 78, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 183, 166, 101, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 102, 85, 40, 48, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 185, 172, 115, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 59, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 183, 166, 101, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 59, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 181, 160, 87, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 175, 158, 120, 66, 179, 156, 77, 255, 238, 224, 140, 255, 215, 191, 98, 255, 178, 154, 73, 255, 22, 18, 14, 255, 117, 98, 45, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 157, 163, 255, 199, 183, 136, 255, 226, 206, 116, 255, 178, 154, 73, 255, 22, 18, 14, 255, 82, 68, 37, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 152, 157, 163, 118, 152, 157, 163, 255, 254, 254, 253, 255, 169, 147, 81, 255, 22, 18, 14, 255, 117, 98, 45, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 118, 110, 113, 117, 255, 81, 84, 87, 255, 0, 0, 0, 255, 82, 68, 37, 40, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 224, 0, 0, 0, 118, 81, 84, 87, 104, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintPencil
end

function load_image_PaintColorPicker()
  local PaintColorPicker = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 1, 1, 1, 85, 0, 0, 1, 192, 0, 0, 0, 192, 0, 0, 0, 85, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 7, 11, 15, 37, 8, 12, 16, 70, 79, 81, 83, 224, 205, 205, 205, 255, 136, 138, 142, 255, 11, 13, 15, 203, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 9, 15, 21, 119, 18, 26, 37, 255, 68, 70, 72, 255, 88, 93, 99, 255, 117, 120, 126, 255, 84, 86, 91, 255, 2, 2, 2, 194, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 15, 21, 30, 31, 23, 34, 49, 235, 49, 56, 65, 255, 70, 72, 72, 255, 54, 56, 58, 255, 21, 22, 22, 199, 0, 0, 0, 85, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 20, 30, 42, 42, 21, 32, 45, 237, 49, 56, 65, 255, 7, 9, 13, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 202, 208, 222, 255, 173, 183, 202, 255, 6, 10, 15, 236, 2, 4, 5, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 202, 208, 222, 255, 143, 156, 181, 255, 68, 88, 114, 255, 1, 1, 3, 33, 0, 0, 0, 111, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 214, 220, 230, 255, 143, 156, 181, 255, 68, 88, 114, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 215, 221, 231, 255, 143, 156, 181, 255, 65, 85, 112, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 255, 255, 255, 255, 216, 220, 231, 255, 143, 156, 181, 255, 65, 85, 112, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 152, 166, 185, 255, 216, 220, 231, 218, 143, 156, 181, 255, 66, 86, 113, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 43, 134, 240, 46, 43, 134, 240, 107, 152, 166, 185, 255, 255, 255, 255, 255, 69, 89, 114, 255, 51, 72, 99, 255, 43, 134, 240, 236, 43, 134, 240, 204, 43, 133, 240, 161, 43, 132, 239, 107, 43, 130, 239, 46, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 43, 133, 239, 170, 43, 133, 240, 255, 87, 105, 130, 255, 79, 97, 123, 255, 43, 134, 240, 255, 43, 134, 240, 255, 43, 135, 240, 255, 43, 134, 240, 255, 43, 134, 240, 255, 43, 134, 240, 255, 43, 133, 239, 170, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 42, 120, 237, 46, 42, 124, 238, 107, 42, 125, 238, 161, 42, 126, 238, 204, 42, 128, 238, 236, 43, 130, 239, 253, 43, 131, 239, 236, 43, 131, 239, 204, 43, 131, 239, 161, 43, 129, 239, 107, 42, 127, 238, 46, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintColorPicker
end

function load_image_PaintEllipse()
  local PaintEllipse = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 20, 0, 0, 0, 84, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 84, 0, 0, 0, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 16, 0, 0, 0, 155, 0, 0, 0, 239, 0, 0, 0, 175, 0, 0, 0, 131, 0, 0, 0, 131, 0, 0, 0, 175, 0, 0, 0, 239, 0, 0, 0, 155, 0, 0, 0, 16, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 215, 0, 0, 0, 143, 0, 0, 0, 16, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 16, 0, 0, 0, 143, 0, 0, 0, 215, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 199, 0, 0, 0, 120, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 199, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 0, 0, 0, 60, 0, 0, 0, 211, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 211, 0, 0, 0, 60, 255, 255, 255, 0, 
      255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 139, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 139, 0, 0, 0, 120, 255, 255, 255, 0, 
      255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 135, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 135, 0, 0, 0, 120, 255, 255, 255, 0, 
      255, 255, 255, 0, 0, 0, 0, 68, 0, 0, 0, 211, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 211, 0, 0, 0, 68, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 199, 0, 0, 0, 120, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 120, 0, 0, 0, 199, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 36, 0, 0, 0, 231, 0, 0, 0, 135, 0, 0, 0, 12, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 12, 0, 0, 0, 135, 0, 0, 0, 231, 0, 0, 0, 36, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 20, 0, 0, 0, 163, 0, 0, 0, 239, 0, 0, 0, 171, 0, 0, 0, 131, 0, 0, 0, 131, 0, 0, 0, 171, 0, 0, 0, 239, 0, 0, 0, 163, 0, 0, 0, 20, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 88, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 88, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintEllipse
end

function load_image_PaintRect()
  local PaintRect = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 254, 0, 0, 0, 247, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintRect
end

function load_image_PaintOval()
  local PaintOval = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 135, 0, 0, 0, 211, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 211, 0, 0, 0, 135, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 80, 0, 0, 0, 239, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 239, 0, 0, 0, 80, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 48, 0, 0, 0, 251, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 48, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 183, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 183, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 247, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 247, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 183, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 183, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 56, 0, 0, 0, 251, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 251, 0, 0, 0, 56, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 84, 0, 0, 0, 243, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 243, 0, 0, 0, 84, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 24, 0, 0, 0, 139, 0, 0, 0, 211, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 211, 0, 0, 0, 139, 0, 0, 0, 24, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintOval
end

function load_image_PaintBox()
  local PaintBox = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 254, 0, 0, 0, 247, 0, 0, 0, 239, 0, 0, 0, 247, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintBox
end

function load_image_PaintZoomGrid()
  local PaintZoomGrid = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 110, 155, 223, 255, 255, 255, 255, 0, 255, 255, 255, 0, 106, 151, 219, 255, 255, 255, 255, 0, 255, 255, 255, 0, 95, 142, 210, 255, 255, 255, 255, 0, 255, 255, 255, 0, 84, 129, 201, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 110, 155, 223, 255, 255, 255, 255, 0, 255, 255, 255, 0, 102, 147, 217, 255, 255, 255, 255, 0, 255, 255, 255, 0, 92, 137, 207, 255, 255, 255, 255, 0, 255, 255, 255, 0, 80, 125, 197, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 110, 155, 223, 255, 110, 155, 223, 255, 107, 152, 222, 255, 104, 151, 219, 255, 103, 148, 216, 255, 100, 145, 213, 255, 97, 142, 210, 255, 93, 138, 206, 255, 88, 133, 203, 255, 84, 129, 201, 255, 80, 125, 197, 255, 76, 121, 193, 255, 72, 117, 189, 255, 68, 113, 183, 255, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 106, 149, 219, 255, 255, 255, 255, 0, 255, 255, 255, 0, 97, 142, 210, 255, 255, 255, 255, 0, 255, 255, 255, 0, 84, 131, 199, 255, 255, 255, 255, 0, 255, 255, 255, 0, 72, 117, 187, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 103, 148, 216, 255, 255, 255, 255, 0, 255, 255, 255, 0, 92, 137, 207, 255, 255, 255, 255, 0, 255, 255, 255, 0, 81, 125, 196, 255, 255, 255, 255, 0, 255, 255, 255, 0, 68, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 104, 151, 219, 255, 104, 148, 216, 255, 100, 145, 213, 255, 97, 142, 210, 255, 92, 137, 207, 255, 88, 135, 203, 255, 84, 129, 199, 255, 80, 125, 195, 255, 76, 121, 193, 255, 70, 117, 189, 255, 68, 112, 183, 255, 62, 109, 181, 255, 60, 105, 177, 255, 57, 102, 174, 255, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 97, 142, 210, 255, 255, 255, 255, 0, 255, 255, 255, 0, 84, 129, 199, 255, 255, 255, 255, 0, 255, 255, 255, 0, 72, 117, 187, 255, 255, 255, 255, 0, 255, 255, 255, 0, 60, 105, 177, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 93, 138, 206, 255, 255, 255, 255, 0, 255, 255, 255, 0, 80, 125, 195, 255, 255, 255, 255, 0, 255, 255, 255, 0, 66, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 56, 103, 173, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 95, 140, 212, 255, 92, 137, 207, 255, 88, 133, 203, 255, 84, 129, 199, 255, 80, 125, 195, 255, 76, 121, 193, 255, 72, 117, 187, 255, 68, 113, 185, 255, 64, 107, 181, 255, 59, 105, 178, 255, 55, 101, 174, 255, 53, 98, 170, 255, 49, 95, 168, 255, 48, 91, 165, 255, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 84, 131, 199, 255, 255, 255, 255, 0, 255, 255, 255, 0, 70, 117, 189, 255, 255, 255, 255, 0, 255, 255, 255, 0, 60, 105, 177, 255, 255, 255, 255, 0, 255, 255, 255, 0, 49, 95, 168, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 82, 125, 195, 255, 255, 255, 255, 0, 255, 255, 255, 0, 68, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 57, 102, 174, 255, 255, 255, 255, 0, 255, 255, 255, 0, 46, 92, 165, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 84, 129, 199, 255, 80, 125, 195, 255, 76, 121, 191, 255, 72, 117, 189, 255, 66, 113, 185, 255, 64, 109, 181, 255, 60, 105, 177, 255, 55, 102, 174, 255, 52, 98, 171, 255, 49, 95, 168, 255, 46, 91, 166, 255, 44, 90, 163, 255, 42, 88, 161, 255, 42, 88, 161, 255, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 72, 117, 187, 255, 255, 255, 255, 0, 255, 255, 255, 0, 60, 107, 177, 255, 255, 255, 255, 0, 255, 255, 255, 0, 50, 95, 167, 255, 255, 255, 255, 0, 255, 255, 255, 0, 42, 88, 161, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 68, 113, 185, 255, 255, 255, 255, 0, 255, 255, 255, 0, 56, 101, 173, 255, 255, 255, 255, 0, 255, 255, 255, 0, 46, 92, 165, 255, 255, 255, 255, 0, 255, 255, 255, 0, 42, 88, 161, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintZoomGrid
end

function load_image_PaintFill()
  local PaintFill = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 53, 53, 86, 59, 59, 59, 111, 108, 108, 108, 82, 127, 127, 127, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 54, 54, 122, 72, 72, 72, 7, 119, 122, 124, 117, 124, 124, 130, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 77, 76, 154, 144, 166, 188, 23, 158, 169, 181, 191, 144, 151, 159, 194, 134, 147, 174, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 124, 126, 129, 197, 141, 160, 183, 179, 212, 219, 225, 254, 157, 162, 166, 254, 163, 180, 200, 168, 159, 175, 191, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, 141, 158, 45, 130, 143, 155, 245, 218, 225, 232, 250, 222, 232, 239, 255, 136, 139, 142, 255, 205, 217, 227, 252, 148, 167, 189, 163, 155, 155, 184, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 148, 170, 24, 134, 155, 174, 172, 213, 220, 227, 254, 218, 233, 243, 255, 197, 207, 217, 255, 149, 149, 150, 255, 232, 241, 245, 255, 179, 196, 213, 252, 129, 147, 172, 164, 75, 103, 144, 37, 17, 51, 102, 15, 0, 0, 0, 0, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 134, 147, 174, 19, 122, 146, 168, 179, 216, 223, 228, 252, 217, 231, 242, 255, 213, 227, 238, 255, 159, 162, 164, 255, 128, 129, 128, 255, 228, 235, 239, 255, 171, 197, 218, 255, 136, 162, 190, 253, 87, 116, 156, 227, 37, 75, 150, 183, 0, 31, 107, 57, 0, 0, 0, 0, 
      0, 0, 0, 0, 120, 134, 161, 19, 126, 147, 168, 157, 209, 217, 225, 245, 217, 231, 241, 255, 203, 217, 232, 255, 242, 244, 245, 255, 192, 192, 191, 255, 164, 166, 169, 255, 202, 213, 223, 255, 158, 176, 194, 255, 126, 154, 184, 255, 103, 134, 168, 255, 76, 110, 169, 255, 49, 93, 175, 201, 37, 66, 132, 27, 
      122, 132, 160, 27, 102, 124, 149, 172, 194, 209, 220, 241, 213, 228, 239, 246, 204, 218, 232, 249, 241, 242, 244, 255, 247, 245, 245, 255, 243, 244, 243, 255, 222, 228, 234, 255, 192, 203, 214, 255, 159, 172, 185, 255, 138, 152, 168, 255, 84, 116, 151, 248, 74, 104, 158, 246, 83, 129, 213, 243, 77, 108, 169, 92, 
      125, 134, 152, 55, 111, 131, 154, 211, 189, 201, 214, 255, 214, 223, 234, 254, 238, 240, 243, 236, 248, 246, 245, 241, 242, 243, 243, 254, 221, 228, 234, 255, 192, 203, 214, 255, 165, 178, 192, 255, 142, 155, 169, 255, 98, 117, 137, 243, 77, 94, 120, 121, 46, 82, 158, 171, 87, 131, 209, 247, 85, 114, 171, 122, 
      0, 255, 255, 1, 134, 140, 167, 38, 137, 155, 179, 206, 218, 223, 230, 254, 244, 242, 243, 252, 242, 244, 243, 239, 220, 228, 234, 252, 192, 202, 214, 255, 164, 176, 190, 255, 140, 154, 168, 255, 92, 112, 132, 243, 75, 91, 114, 111, 102, 102, 153, 5, 29, 61, 136, 140, 68, 109, 192, 244, 84, 113, 170, 94, 
      0, 0, 0, 0, 0, 0, 255, 1, 157, 173, 195, 47, 148, 166, 191, 205, 204, 210, 220, 248, 227, 231, 235, 253, 193, 204, 216, 255, 163, 175, 189, 255, 138, 151, 166, 255, 95, 113, 134, 242, 74, 88, 113, 110, 95, 127, 127, 8, 0, 0, 0, 0, 35, 66, 135, 145, 72, 109, 182, 239, 91, 120, 178, 53, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 142, 165, 34, 103, 124, 151, 197, 158, 172, 187, 252, 164, 176, 189, 255, 134, 148, 162, 254, 96, 113, 133, 245, 75, 87, 110, 122, 102, 102, 102, 5, 0, 0, 0, 0, 0, 0, 0, 0, 60, 91, 151, 173, 84, 115, 173, 195, 98, 117, 176, 13, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 110, 119, 30, 73, 96, 120, 204, 107, 126, 144, 255, 106, 123, 141, 255, 102, 115, 135, 152, 139, 150, 162, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 92, 154, 173, 85, 115, 173, 119, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 82, 115, 31, 49, 79, 109, 212, 92, 110, 134, 169, 143, 159, 175, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 93, 154, 163, 63, 89, 153, 20, 0, 0, 0, 0, 
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 118, 140, 58, 85, 106, 148, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 92, 154, 33, 0, 0, 0, 0, 0, 0, 0, 0, 
    },
  }
  return PaintFill
end

function load_image_PaintText()
  local PaintText = iup.imagergba
  {
    width = 16,
    height = 16,
    pixels = {
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 36, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 96, 0, 0, 0, 72, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 255, 0, 0, 0, 203, 0, 0, 0, 124, 0, 0, 0, 135, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 215, 0, 0, 0, 96, 0, 0, 0, 131, 0, 0, 0, 243, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 163, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 44, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 48, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 116, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 64, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 191, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 96, 0, 0, 0, 187, 0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 243, 0, 0, 0, 116, 0, 0, 0, 48, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
      255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 
    },
  }
  return PaintText
end


--********************************** Utilities *****************************************

function str_splitfilename(filename)
  return string.match(filename, "(.-)([^\\/]-%.?([^%.\\/]*))$")
end

function str_fileext(filename)
  local path, title, ext = str_splitfilename(filename)
  return ext
end

function str_filetitle(filename)
  local path, title, ext = str_splitfilename(filename)
  return title
end

function show_error(message, is_error)
  local dlg = iup.messagedlg{
    parentdialog = iup.GetGlobal("PARENTDIALOG"),
    buttons = "OK",
    value = message,
  }
  if (is_error) then
    dlg.dialogtype = "ERROR"
    dlg.title = "Error"
  else
    dlg.dialogtype = "WARNING"
    dlg.title = "Warning"
  end
  dlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
  dlg:destroy()
end

function read_file(filename)
  local image, err = im.FileImageLoadBitmap(filename, 0)
  if (err) then
    show_error(im.ErrorStr(err), true)
  end
  return image
end

function write_file(filename, image)
  local format = image:GetAttribString("FileFormat")
  local err = im.FileImageSave(filename, format, image)
  if (err and err ~= im.ERR_NONE) then
    show_error(im.ErrorStr(err), true)
    return false
  end
  return true
end

-- extracted from the SCROLLBAR attribute documentation 
function scroll_update(ih, view_width, view_height)
  -- view_width and view_height is the virtual space size 
  -- here we assume XMIN=0, XMAX=1, YMIN=0, YMAX=1 
  local scrollbar_size = tonumber(iup.GetGlobal("SCROLLBARSIZE"))
  local border = 1
  if (ih.border ~= "YES") then 
    border = 0
  end

  local elem_width, elem_height = string.match(ih.rastersize, "(%d*)x(%d*)")
  elem_width = tonumber(elem_width)
  elem_height = tonumber(elem_height)

  -- if view is greater than canvas in one direction,
  -- then it has scrollbars,
  -- but this affects the opposite direction 
  elem_width = elem_width - 2 * border  -- remove BORDER (always size=1) 
  elem_height = elem_height - 2 * border
  local canvas_width = elem_width
  local canvas_height = elem_height
  if (view_width > elem_width) then  -- check for horizontal scrollbar 
    canvas_height = canvas_height - scrollbar_size  -- affect vertical size 
  end
  if (view_height > elem_height) then 
    canvas_width = canvas_width - scrollbar_size
  end
  if (view_width <= elem_width and view_width > canvas_width) then  -- check if still has horizontal scrollbar 
    canvas_height = canvas_height - scrollbar_size
  end
  if (view_height <= elem_height and view_height > canvas_height) then
    canvas_width = canvas_width - scrollbar_size
  end
  if (canvas_width < 0) then canvas_width = 0 end
  if (canvas_height < 0) then canvas_height = 0 end

  ih.dx = canvas_width / view_width
  ih.dy = canvas_height / view_height
end

function scroll_calc_center(ih)
  local x = tonumber(ih.posx) + tonumber(ih.dx) / 2
  local y = tonumber(ih.posy) + tonumber(ih.dy) / 2
  return x, y
end

function scroll_center(ih, old_center_x, old_center_y)
  -- always update the scroll position
  -- keeping it proportional to the old position
  -- relative to the center of the ih. 

  local dx = tonumber(ih.dx)
  local dy = tonumber(ih.dy)

  local posx = old_center_x - dx / 2
  local posy = old_center_y - dy / 2

  if (posx < 0) then posx = 0 end
  if (posx > 1 - dx) then posx = 1 - dx end

  if (posy < 0) then posy = 0 end
  if (posy > 1 - dy) then posy = 1 - dy end

  ih.posx = posx
  ih.posy = posy
end

function scroll_move(ih, canvas_width, canvas_height, move_x, move_y, view_width, view_height)
  local posy = 0
  local posx = 0

  if (move_x == 0 and move_y == 0) then
    return
  end
  if (canvas_height < view_height) then
    posy = tonumber(ih.posy)
    posy = posy - (move_y/view_height)
  end

  if (canvas_width < view_width) then
    posx = tonumber(ih.posx)
    posx = posx - (move_x/view_width)
  end

  if (posx ~= 0 or posy ~= 0) then
    ih.posx = posx
    ih.posy = posy
    iup.Update(ih)
  end
end

function zoom_update(ih, zoom_index)
  local zoom_lbl = iup.GetDialogChild(ih, "ZOOMLABEL")
  local dlg = iup.GetDialog(ih)
  local canvas = dlg.canvas
  local image = canvas.image
  local zoom_factor = 2^zoom_index

  zoom_lbl.title = string.format("%.0f%%", math.floor(zoom_factor * 100))

  if (image) then
    local view_width = math.floor(zoom_factor * image:Width())
    local view_height = math.floor(zoom_factor * image:Height())

    local old_center_x, old_center_y = scroll_calc_center(canvas)

    scroll_update(canvas, view_width, view_height)

    scroll_center(canvas, old_center_x, old_center_y)
  end
  iup.Update(canvas)
end

function xy_stack_push(q, x, y)
 local new_q = {}
 new_q.x = x
 new_q.y = y
 new_q.next = q
 return new_q
end

function xy_stack_pop(q)
  local next_q = q.next
  return next_q
end

function color_is_similar(color1, color2, tol)
  local diff_r = cd.Red(color1) - cd.Red(color2)
  local diff_g = cd.Green(color1) - cd.Green(color2)
  local diff_b = cd.Blue(color1) - cd.Blue(color2)
  local sqr_dist = diff_r*diff_r + diff_g*diff_g + diff_b*diff_b
  -- max value = 255*255*3 = 195075
  -- sqrt(195075)=441
  if (sqr_dist < tol) then
    return true
  else
    return false
  end
end

function image_flood_fill(image, start_x, start_y, replace_color, tol_percent)
  local r = image[0]
  local g = image[1]
  local b = image[2]
  local color

  local target_color = cd.EncodeColor(r[start_y][start_x], g[start_y][start_x], b[start_y][start_x])
  
  if (target_color == replace_color) then
    return
  end
  local tol = math.floor((441 * tol_percent) / 100)
  tol = tol*tol  -- this is too high
  tol = tol / 50 -- empirical reduce. TODO: What is the best formula?

  -- very simple 4 neighbors stack based flood fill

  -- a color in the xy_stack is always similar to the target color,
  -- and it was already replaced
  local q = xy_stack_push(nil, start_x, start_y)
  r[start_y][start_x], g[start_y][start_x], b[start_y][start_x] = cd.DecodeColor(replace_color)
  
  while (q) do
    local cur_x = q.x
    local cur_y = q.y
    q = xy_stack_pop(q)
    
    -- right 
    if (cur_x < image:Width() - 1) then
      color = cd.EncodeColor(r[cur_y][cur_x+1], g[cur_y][cur_x+1], b[cur_y][cur_x+1])
      if (color ~= replace_color and color_is_similar(color, target_color, tol)) then
        q = xy_stack_push(q, cur_x+1, cur_y)
        r[cur_y][cur_x+1], g[cur_y][cur_x+1], b[cur_y][cur_x+1] = cd.DecodeColor(replace_color)
      end
    end

    -- left 
    if (cur_x > 0) then
      color = cd.EncodeColor(r[cur_y][cur_x-1], g[cur_y][cur_x-1], b[cur_y][cur_x-1])
      if (color ~= replace_color and color_is_similar(color, target_color, tol)) then
        q = xy_stack_push(q, cur_x-1, cur_y)
        r[cur_y][cur_x-1], g[cur_y][cur_x-1], b[cur_y][cur_x-1] = cd.DecodeColor(replace_color)
      end
    end

    -- top
    if (cur_y < image:Height() - 1) then
      color = cd.EncodeColor(r[cur_y+1][cur_x], g[cur_y+1][cur_x], b[cur_y+1][cur_x])
      if (color ~= replace_color and color_is_similar(color, target_color, tol)) then
        q = xy_stack_push(q, cur_x, cur_y+1)
        r[cur_y+1][cur_x], g[cur_y+1][cur_x], b[cur_y+1][cur_x] = cd.DecodeColor(replace_color)
      end
    end

    -- bottom
    if (cur_y > 0) then
      color = cd.EncodeColor(r[cur_y-1][cur_x], g[cur_y-1][cur_x], b[cur_y-1][cur_x])
      if (color ~= replace_color and color_is_similar(color, target_color, tol)) then
        q = xy_stack_push(q, cur_x, cur_y-1)
        r[cur_y-1][cur_x], g[cur_y-1][cur_x], b[cur_y-1][cur_x] = cd.DecodeColor(replace_color)
      end
    end
  end
end

function image_fill_white(image)
  local x, y
  local r = image[0]
  local g = image[1]
  local b = image[2]
  for y = 0, image:Height()-1 do
    local r_line = r[y]
    local g_line = g[y]
    local b_line = b[y]
    for x = 0, image:Width()-1 do
      r_line[x] = 255
      g_line[x] = 255
      b_line[x] = 255
    end
  end
end

function set_new_image(canvas, image, filename, dirty)
  local dlg = iup.GetDialog(canvas)
  local old_image = canvas.image
  local size_lbl = iup.GetDialogChild(canvas, "SIZELABEL")
  local zoom_val = iup.GetDialogChild(canvas, "ZOOMVAL")

  if (filename) then
    canvas.filename = filename
    dlg.title = str_filetitle(filename).." - Simple Paint"
  else
    dlg.title = "Untitled - Simple Paint"
    canvas.filename = nil
  end

  -- we are going to support only RGB images with no alpha
  image:RemoveAlpha()
  if (image:ColorSpace() ~= im.RGB) then
    local new_image = im.ImageCreateBased(image, nil, nil, im.RGB, nil)        

    im.ConvertColorSpace(image, new_image)
    image:Destroy()

    image = new_image
  end

  -- default file format 
  local format = image:GetAttribString("FileFormat")
  if (not format) then
    image:SetAttribString("FileFormat", "JPEG")
  end

  canvas.dirty = dirty
  canvas.image = image

  size_lbl.title = image:Width().." x "..image:Height().." px"

  if (old_image) then
    old_image:Destroy()
  end

  zoom_val.value = 0
  zoom_update(canvas, 0)
end

function check_new_file(dlg)
  local canvas = dlg.canvas
  local image = canvas.image
  if (not image) then
    local config = canvas.config
    local width = config:GetVariableDef("NewImage", "Width", 640)
    local height = config:GetVariableDef("NewImage", "Height", 480)

    local image = im.ImageCreate(width, height, im.RGB, im.BYTE)
    image_fill_white(image)
    
    set_new_image(canvas, image, nil, nil)
  end
end

function open_file(ih, filename)
  local image = read_file(filename)
  if (image) then
    local dlg = iup.GetDialog(ih)
    local canvas = dlg.canvas
    local config = canvas.config
  
    set_new_image(canvas, image, filename, nil)
    
    config:RecentUpdate(filename)
  end
end

function save_file(canvas)
  if (write_file(canvas.filename, canvas.image)) then
    canvas.dirty = nil
  end
end

function set_file_format(image, filename)
  local ext = str_fileext(filename)
  ext:lower()
  local format = "JPEG"
  if (ext == "jpg" or ext == "jpeg") then
    format = "JPEG"
  elseif (ext == "bmp") then
    format = "BMP"
  elseif (ext == "png") then
    format = "PNG"
  elseif (ext == "tga") then
    format = "TGA"
  elseif (ext == "tif" or ext == "tiff") then
    format = "TIFF"
  end
  image:SetAttribString("FileFormat", format)
end

function saveas_file(canvas, filename)
  local image = canvas.image

  set_file_format(image, filename)

  if (write_file(filename, image)) then
    local dlg = iup.GetDialog(canvas)
    local config = canvas.config
    
    dlg.title = str_filetitle(filename).." - Simple Paint"
    canvas.filename = filename
    canvas.dirty = nil
    
    config:RecentUpdate(filename)
  end
end

function save_check(ih)
  local dlg = iup.GetDialog(ih)
  local canvas = dlg.canvas
  
  if (canvas.dirty) then
    local resp = iup.Alarm("Warning", "File not saved! Save it now?", "Yes", "No", "Cancel")
    if resp == 1 then -- save the changes and continue
      save_file(canvas)
    elseif resp == 3 then  -- cancel
      return false
    else  -- ignore the changes and continue
    end
  end
  return true
end

function toggle_bar_visibility(item, bar)
  if (item.value == "ON") then
    bar.floating = "YES"
    bar.visible = "NO"
    item.value = "OFF"
  else
    bar.floating = "NO"
    bar.visible = "YES"
    item.value = "ON"
  end
  iup.Refresh(bar)  -- refresh the dialog layout
end

function select_file(parent_dlg, is_open)
  local filedlg = iup.filedlg{
    extfilter="Image Files|*.bmp;*.jpg;*.png;*.tif;*.tga|All Files|*.*|",
    parentdialog = parent_dlg,
    directory = config:GetVariable("MainWindow", "LastDirectory"),
    }
    
  if (is_open) then
    filedlg.dialogtype = "OPEN"
  else
    filedlg.dialogtype = "SAVE"
    filedlg.file = canvas.filename
  end

  filedlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)
  
  if (tonumber(filedlg.status) ~= -1) then
    local filename = filedlg.value
    if (is_open) then
      open_file(parent_dlg, filename)
    else
      saveas_file(canvas, filename)    
    end

    config:SetVariable("MainWindow", "LastDirectory", filedlg.directory)
  end
  
  filedlg:destroy()
end

function view_fit_rect(canvas_width, canvas_height, image_width, image_height)
  local view_width = canvas_width
  local view_height = (canvas_width * image_height) / image_width

  if (view_height > canvas_height) then 
    view_height = canvas_height
    view_width = (canvas_height * image_width) / image_height
  end
  
  return view_width, view_height
end

function view_zoom_rect(ih, image_width, image_height)
  local zoom_val = iup.GetDialogChild(ih, "ZOOMVAL")
  local zoom_index = tonumber(zoom_val.value)
  local zoom_factor = 2^zoom_index
  local x, y

  local posy = tonumber(ih.posy)
  local posx = tonumber(ih.posx)
  
  local canvas_width, canvas_height = string.match(ih.drawsize,"(%d*)x(%d*)")
  canvas_width = tonumber(canvas_width)
  canvas_height = tonumber(canvas_height)

  local view_width = math.floor(zoom_factor * image_width)
  local view_height = math.floor(zoom_factor * image_height)

  if (canvas_width < view_width) then
    x = math.floor(-posx * view_width)
  else
    x = math.floor((canvas_width - view_width) / 2)
  end

  if (canvas_height < view_height) then
    -- posy is top-bottom, CD is bottom-top.
    -- invert posy reference (YMAX-DY - POSY)
    dy = tonumber(canvas.dy)
    posy = 1 - dy - posy
    y = math.floor(-posy * view_height)
  else
    y = math.floor((canvas_height - view_height) / 2)
  end

  return zoom_factor, x, y, view_width, view_height
end

function tool_get_text_enter_cb()
  return iup.CLOSE
end

function tool_get_text()
  local text, dlg
  
  text = iup.text{expand = "YES", value = toolbox.tooltext, font = toolbox.toolfont, visiblecolumns = 20}

  dlg = iup.dialog{text, title = "Enter Text:", minbox = "NO", maxbox = "NO"}
  dlg.parentdialog = toolbox

  iup.Popup(dlg, iup.MOUSEPOS, iup.MOUSEPOS)

  toolbox.tooltext = text.value

  iup.Destroy(dlg)
end



--********************************** Main (Part 1/2) *****************************************

-- create all the elements that will have callbacks in Lua prior to callbacks definition

config = iup.config{}
config.app_name = "simple_paint"
config:Load()

canvas = iup.canvas{
  scrollbar = "Yes",
  dirty = nil, -- custom attribute
  dx = 0,
  dy = 0,
  config = config,
}

item_new = iup.item{title = "&New...\tCtrl+N", image = "IUP_FileNew"}
item_open = iup.item{title = "&Open...\tCtrl+O", image = "IUP_FileOpen"}
item_save = iup.item{title="&Save\tCtrl+S"}
item_saveas = iup.item{title="Save &As...", image = "IUP_FileSave"}
item_revert = iup.item{title="&Revert"}
item_pagesetup = iup.item{title="Page Set&up..."}
item_print = iup.item{title="&Print\tCtrl+P"}
item_exit = iup.item{title="E&xit"}
item_copy = iup.item{title="&Copy\tCtrl+C", image = "IUP_EditCopy"}
item_paste = iup.item{title="&Paste\tCtrl+V", image = "IUP_EditPaste"}
item_background = iup.item{title="&Background..."}
item_zoomin = iup.item{title="Zoom &In\tCtrl++", image = "IUP_ZoomIn"}
item_zoomout = iup.item{title="Zoom &Out\tCtrl+-", image = "IUP_ZoomOut"}
item_actualsize = iup.item{title="&Actual Size\tCtrl+0", image = "IUP_ZoomActualSize"}
item_toolbar = iup.item{title="&Toobar", value="ON"}
item_statusbar = iup.item{title="&Statusbar", value="ON"}
item_help = iup.item{title="&Help..."}
item_about = iup.item{title="&About..."}

item_zoomgrid = iup.item{title = "&Zoom Grid", action = item_zoomgrid_action_cb, VALUE = "ON", name = "ZOOMGRID"}
item_toolbox = iup.item{title = "&Toobox", action = item_toolbox_action_cb, name = "TOOLBOXMENU"}


recent_menu = iup.menu{}

file_menu = iup.menu{
  item_new,
  item_open,
  item_save,
  item_saveas,
  item_revert,
  iup.separator{},
  item_pagesetup,
  item_print,
  iup.separator{},
  iup.submenu{title="Recent &Files", recent_menu},
  iup.separator{},
  item_exit
  }

edit_menu = iup.menu{
  item_copy,
  item_paste,
  }

view_menu = iup.menu{
  item_zoomin, 
  item_zoomout, 
  item_actualsize,
  item_zoomgrid,
  iup.separator{},
  item_background,
  iup.separator{},
  item_toolbar, 
  item_toolbox,
  item_statusbar, 
  }
help_menu = iup.menu{item_help, item_about}

sub_menu_file = iup.submenu{file_menu, title = "&File"}
sub_menu_edit = iup.submenu{edit_menu, title = "&Edit"}
sub_menu_view = iup.submenu{title = "&View", view_menu}
sub_menu_help = iup.submenu{help_menu, title = "&Help"}

menu = iup.menu{
  sub_menu_file, 
  sub_menu_edit, 
  sub_menu_view, 
  sub_menu_help,
  }


--********************************** Callbacks *****************************************


function canvas:action()
  local image = canvas.image
  local canvas_width, canvas_height = string.match(canvas.drawsize,"(%d*)x(%d*)")
  local cd_canvas = canvas.cdCanvas

  canvas_width = tonumber(canvas_width)
  canvas_height = tonumber(canvas_height)

  cd_canvas:Activate()

  -- draw the background 
  local background = config:GetVariableDef("Canvas", "Background", "208 208 208")
  local r, g, b = string.match(background, "(%d*) (%d*) (%d*)")
  cd_canvas:Background(cd.EncodeColor(r, g, b))
  cd_canvas:Clear()

  -- draw the image at the center of the canvas 
  if (image) then
    local zoom_factor, x, y, view_width, view_height = view_zoom_rect(canvas, image:Width(), image:Height())

    -- black line around the image
    cd_canvas:Foreground(cd.BLACK)
    cd_canvas:Rect(x - 1, x + view_width, y - 1, y + view_height)

    image:cdCanvasPutImageRect(cd_canvas, x, y, view_width, view_height, 0, 0, 0, 0)
    
    if (config:GetVariable("Canvas", "ZoomGrid") == "ON") then
      zoom_val = iup.GetDialogChild(canvas, "ZOOMVAL")
      zoom_index = tonumber(zoom_val.value)
      if (zoom_index > 1) then
        local ix, iy
        local zoom_factor = math.pow(2, zoom_index)
        cd_canvas:Foreground(cd.GRAY)
        for ix = 0, image:Width()-1 do
          local gx = math.floor(ix * zoom_factor)
          cd_canvas:Line(gx + x, y, gx + x, y + view_height)
        end
        for iy = 0, image:Height()-1 do
          local gy = math.floor(iy * zoom_factor)
          cd_canvas:Line(x, gy + y, x + view_width, gy + y)
        end
      end
    end

    if (canvas.overlay) then
      local start_x = tonumber(canvas.start_x)
      local start_y = tonumber(canvas.start_y)
      local end_x = tonumber(canvas.end_x)
      local end_y = tonumber(canvas.end_y)
      local line_width = tonumber(toolbox.toolwidth)
      local line_style = tonumber(toolbox.toolstyle - 1)
      local r, g, b = string.match(toolbox.toolcolor, "(%d*) (%d*) (%d*)")
      
      cd_canvas:TransformTranslate(x, y)
      cd_canvas:TransformScale(view_width / image:Width(), view_height / image:Height())

      cd_canvas:Foreground(cd.EncodeColor(r, g, b))
      cd_canvas:LineWidth(line_width)
      if (line_width == 1) then
        cd_canvas:LineStyle(line_style)
    end
      if (canvas.overlay == "LINE") then
        cd_canvas:Line(start_x, start_y, end_x, end_y)
      elseif (canvas.overlay == "RECT") then
        cd_canvas:Rect(start_x, end_x, start_y, end_y)
      elseif (canvas.overlay == "BOX") then
        cd_canvas:Box(start_x, end_x, start_y, end_y)
      elseif (canvas.overlay == "ELLIPSE") then
        cd_canvas:Arc((end_x + start_x) / 2, (end_y + start_y) / 2, math.abs(end_x - start_x), math.abs(end_y - start_y), 0, 360)
      elseif (canvas.overlay == "OVAL") then
        cd_canvas:Sector((end_x + start_x) / 2, (end_y + start_y) / 2, math.abs(end_x - start_x), math.abs(end_y - start_y), 0, 360)
      elseif (canvas.overlay == "TEXT") then
        cd_canvas:TextAlignment(cd.SOUTH_WEST)
        cd_canvas:NativeFont(toolbox.toolfont)
        cd_canvas:Text(end_x, end_y, toolbox.tooltext)
      end
      cd_canvas:Transform(nil)
    end
  end
  cd_canvas:Flush()
end

function canvas:map_cb()
  cd_canvas = cd.CreateCanvas(cd.IUPDBUFFER, canvas)
  canvas.cdCanvas = cd_canvas
end

function canvas:unmap_cb()
  local cd_canvas = canvas.cdCanvas
  cd_canvas:Kill()
end

function round(x)
  if (x < 0) then
    return math.ceil(x - 0.5)
  else
    return math.floor(x + 0.5)
  end
end

function item_zoomout:action()
  local zoom_val = iup.GetDialogChild(self, "ZOOMVAL")
  local zoom_index = tonumber(zoom_val.value)
  zoom_index = zoom_index - 1
  if (zoom_index < -6) then
    zoom_index = -6
  end
  zoom_val.value = round(zoom_index)  -- fixed increments when using buttons 

  zoom_update(self, zoom_index)
end

function item_zoomin:action()
  local zoom_val = iup.GetDialogChild(self, "ZOOMVAL")
  local zoom_index = tonumber(zoom_val.value)
  zoom_index = zoom_index + 1
  if (zoom_index > 6) then
    zoom_index = 6
  end
  zoom_val.value = round(zoom_index)  -- fixed increments when using buttons 

  zoom_update(self, zoom_index)
end

function item_actualsize:action()
  local zoom_val = iup.GetDialogChild(self, "ZOOMVAL")
  zoom_val.value = 0
  zoom_update(self, 0)
end

function canvas:resize_cb()
  local image = canvas.image
  if (image) then
    local zoom_val = iup.GetDialogChild(self, "ZOOMVAL")
    local zoom_index = tonumber(zoom_val.value)
    local zoom_factor = 2^zoom_index

    local view_width = math.floor(zoom_factor * image:Width())
    local view_height = math.floor(zoom_factor * image:Height())

    local old_center_x, old_center_y = scroll_calc_center(canvas)

    scroll_update(canvas, view_width, view_height)

    scroll_center(canvas, old_center_x, old_center_y)
  end
end

function canvas:wheel_cb(delta)
  if (iup.GetGlobal("CONTROLKEY") == "ON") then
    if (delta < 0) then
      item_zoomout:action()
    else
      item_zoomin:action()
    end
  else
    local posy = tonumber(canvas.posy)
    posy = posy - delta * tonumber(canvas.dy) / 10
    canvas.posy = posy
    iup.Update(canvas)
  end
end

function canvas:button_cb(button, pressed, x, y)
  local image = self.image
  if (image) then
    local cursor_x, cursor_y = x, y
    local zoom_factor, view_x, view_y, view_width, view_height = view_zoom_rect(canvas, image:Width(), image:Height())

    -- y is top-down in IUP
    local canvas_width, canvas_height = string.match(canvas.drawsize,"(%d*)x(%d*)") 
    canvas_height = tonumber(canvas_height)
    y = canvas_height - y - 1

    -- inside image area
    if (x > view_x and y > view_y and x < view_x + view_width and y < view_y + view_height) then
      x = x - view_x
      y = y - view_y

      x = math.floor(x / zoom_factor)
      y = math.floor(y / zoom_factor)

      if (x < 0) then x = 0 end
      if (y < 0) then y = 0 end
      if (x > image:Width() - 1) then x = image:Width() - 1 end
      if (y > image:Height() - 1) then y = image:Height() - 1 end

      if (button == iup.BUTTON1) then
        if (pressed == 1) then
          canvas.start_x = x
          canvas.start_y = y
          canvas.start_cursor_x = cursor_x
          canvas.start_cursor_y = cursor_y
        else
          local tool_index = tonumber(toolbox.toolindex)
          if (tool_index == 1) then -- Color Picker 
            local color = toolbox.color
            r = image[0][y][x]
            g = image[1][y][x]
            b = image[2][y][x]
            color.bgcolor = r.." "..g.." "..b
            toolbox.toolcolor = r.." "..g.." "..b
          elseif (tool_index == 2) then -- Pencil
            local start_x = canvas.start_x
            local start_y = canvas.start_y
            local res = tonumber(iup.GetGlobal("SCREENDPI")) / 25.4
            local r, g, b = string.match(toolbox.toolcolor, "(%d*) (%d*) (%d*)")
            local line_width = toolbox.toolwidth
              
            -- do not use line style here */
            local cd_canvas = image:cdCreateCanvas()
            image:SetAttribString("ResolutionUnit", "PDI")
            image:SetAttribReal("XResolution", im.FLOAT, res)
            image:SetAttribReal("YResolution", im.FLOAT, res)
            cd_canvas:Foreground(cd.EncodeColor(r, g, b))
            cd_canvas:LineWidth(line_width)
            cd_canvas:Line(start_x, start_y, x, y)
            cd_canvas:Kill()
  
            canvas.dirty = "Yes"
            iup.Update(canvas)
  
            canvas.start_x = x
            canvas.start_y = y
          elseif (tool_index >= 3 and tool_index <= 8) then -- Shapes
            if (canvas.overlay) then
              local start_x = canvas.start_x
              local start_y = canvas.start_y
              local line_width = toolbox.toolwidth
              local line_style = toolbox.toolstyle - 1
              local res = tonumber(iup.GetGlobal("SCREENDPI")) / 25.4
              local r, g, b = string.match(toolbox.toolcolor, "(%d*) (%d*) (%d*)")
              
              local cd_canvas = image:cdCreateCanvas()
              image:SetAttribString("ResolutionUnit", "PDI")
              image:SetAttribReal("XResolution", im.FLOAT, res)
              image:SetAttribReal("YResolution", im.FLOAT, res)
              cd_canvas:Foreground(cd.EncodeColor(r, g, b))
              cd_canvas:LineWidth(line_width)
              if (line_width == 1) then
                cd_canvas:LineStyle(line_style)
              end
              if (canvas.overlay == "LINE") then
                cd_canvas:Line(start_x, start_y, x, y)
              elseif (canvas.overlay == "RECT") then
                cd_canvas:Rect(start_x, x, start_y, y)
              elseif (canvas.overlay == "BOX") then
                cd_canvas:Box(start_x, x, start_y, y)
              elseif (canvas.overlay == "ELLIPSE") then
                cd_canvas:Arc((x + start_x) / 2, (y + start_y) / 2, math.abs(x - start_x), math.abs(y - start_y), 0, 360)
              elseif (canvas.overlay == "OVAL") then
                cd_canvas:Sector((x + start_x) / 2, (y + start_y) / 2, math.abs(x - start_x), math.abs(y - start_y), 0, 360)
              elseif (canvas.overlay == "TEXT") then
                cd_canvas:TextAlignment(cd.SOUTH_WEST)
                cd_canvas:NativeFont(toolbox.toolfont)
                cd_canvas:Text(x, y, toolbox.tooltext)
              end
  
              cd_canvas:Kill()
  
              canvas.overlay = nil
              canvas.dirty = "Yes"
  
              iup.Update(canvas)
            end
          elseif (tool_index == 9) then -- Fill Color
            local tol_percent = toolbox.toolfilltol
            local r, g, b = string.match(toolbox.toolcolor, "(%d*) (%d*) (%d*)")
            image_flood_fill(image, x, y, cd.EncodeColor(r, g, b), tol_percent)
            canvas.dirty = "Yes"
  
            iup.Update(canvas)
          end
        end
      elseif (button == iup.BUTTON3) then
        if (pressed == 0) then
          local tool_index = tonumber(toolbox.toolindex)
          if (tool_index == 8) then -- Text
            tool_get_text()
          end
        end
      end
    end
  end
  return iup.DEFAULT
end

function canvas:motion_cb(x, y, status)
  local image = self.image
  if (image) then
    local cursor_x, cursor_y = x, y
    local zoom_factor, view_x, view_y, view_width, view_height = view_zoom_rect(canvas, image:Width(), image:Height())

    -- y is top-down in IUP
    local canvas_width, canvas_height = string.match(canvas.drawsize,"(%d*)x(%d*)")
    canvas_height = tonumber(canvas_height)
    y = canvas_height - y - 1

    -- inside image area 
    if (x > view_x and y > view_y and x < view_x + view_width and y < view_y + view_height) then
      local status_lbl = iup.GetDialogChild(self, "STATUSLABEL")

      x = x - view_x
      y = y - view_y

      x = math.floor(x / zoom_factor)
      y = math.floor(y / zoom_factor)

      if (x < 0) then x = 0 end
      if (y < 0) then y = 0 end
      if (x > image:Width() - 1) then x = image:Width() - 1 end
      if (y > image:Height() - 1) then y = image:Height() - 1 end

      local r = image[0][y][x]
      local g = image[1][y][x]
      local b = image[2][y][x]
      
      status_lbl.title = "("..x..", "..y..") = "..r.." "..g.." "..b

      if (iup.isbutton1(status)) then -- button1 is pressed
        local tool_index = tonumber(toolbox.toolindex)
        
        if (tool_index == 0) then -- Pointer 
          local start_cursor_x = tonumber(canvas.start_cursor_x)
          local start_cursor_y = tonumber(canvas.start_cursor_y)

          local canvas_width, canvas_height = string.match(self.drawsize,"(%d*)x(%d*)")
          canvas_width = tonumber(canvas_width)
          canvas_height = tonumber(canvas_height)

          scroll_move(canvas, canvas_width, canvas_height, cursor_x - start_cursor_x, cursor_y - start_cursor_y, view_width, view_height)

          self.start_cursor_x = cursor_x
          self.start_cursor_y = cursor_y
        elseif (tool_index == 2) then -- Pencil */
          local start_x = self.start_x
          local start_y = self.start_y
          local res = tonumber(iup.GetGlobal("SCREENDPI")) / 25.4

          local line_width = tonumber(toolbox.toolwidth)
          r, g, b = string.match(toolbox.toolcolor, "(%d*) (%d*) (%d*)")
          
          -- do not use line style here */
          local cd_canvas = image:cdCreateCanvas()
          image:SetAttribString("ResolutionUnit", "PDI")
          image:SetAttribReal("XResolution", im.FLOAT, res)
          image:SetAttribReal("YResolution", im.FLOAT, res)
          cd_canvas:Foreground(cd.EncodeColor(r, g, b))
          cd_canvas:LineWidth(line_width)
          cd_canvas:Line(start_x, start_y, x, y)
          cd_canvas:Kill()

          self.dirty = "Yes"

          iup.Update(canvas)

          self.start_x = tonumber(x)
          self.start_y = tonumber(y)          
        elseif (tool_index >= 3 and tool_index <= 8) then -- Shapes
          local shapes = {"LINE", "RECT", "BOX", "ELLIPSE", "OVAL", "TEXT"}
          self.end_x = tonumber(x)
          self.end_y = tonumber(y)
          self.overlay = shapes[tool_index - 2]
          iup.Update(self)
        end
      end
    end
  end
end

function zoom_valuechanged_cb(val)
  local zoom_index = tonumber(val.value)
  zoom_update(val, zoom_index)
end

function canvas:dropfiles_cb(filename)
  if (save_check(self)) then
    open_file(self, filename)
  end
end

function file_menu:open_cb()
  if (canvas.dirty) then
    item_save.active = "YES"
  else
    item_save.active = "NO"
  end
  if (canvas.dirty and canvas.filename) then
    item_revert.active = "YES"
  else
    item_revert.active = "NO"
  end
end

function edit_menu:open_cb()
  local clipboard = iup.clipboard{}
  if (clipboard.imageavailable == "NO") then
    item_paste.active = "NO"
  else
    item_paste.active = "YES"
  end
  clipboard:destroy()
end

function config:recent_cb()
  if (save_check(self)) then
    local filename = self.recentfilename
    open_file(self, filename)
  end
end

function item_new:action()
  if save_check(self) then
    local width = config:GetVariableDef("NewImage", "Width", 640)
    local height = config:GetVariableDef("NewImage", "Height", 480)

    local ret, new_width, new_height = iup.GetParam("New Image", nil, "Width: %i[1,]\nHeight: %i[1,]\n", width, height)
    if (ret) then
      local new_image = im.ImageCreate(new_width, new_height, im.RGB, im.BYTE)

      config:SetVariable("NewImage", "Width", new_width)
      config:SetVariable("NewImage", "Height", new_height)

      set_new_image(canvas, new_image, nil, nil)
    end
  end
end

function item_open:action()
  if not save_check(self) then
    return
  end

  select_file(dlg, true)
end

function item_saveas:action()
  select_file(dlg, false)
end

function item_save:action()
  if (not canvas.filename) then
    item_saveas:action()
  else
    -- test again because in can be called using the hot key
    if (canvas.dirty) then
      save_file(canvas)
    end
  end
end

function item_revert:action()
  open_file(self, canvas.filename)
end

function item_pagesetup:action()
  local width = config:GetVariableDef("Print", "MarginWidth", 20)
  local height = config:GetVariableDef("Print", "MarginHeight", 20)

  local ret, new_width, new_height = iup.GetParam("Page Setup", nil, "nMargin Width (mm): %i[1,]\nnMargin Height (mm): %i[1,]\n", width, height)
  if (ret) then
    config:SetVariable("Print", "MarginWidth", new_width)
    config:SetVariable("Print", "MarginHeight", new_height)
  end
end

function item_print:action()
  local title = dlg.title
  local cd_canvas = cd.CreateCanvas(cd.PRINTER, title.." -d")
  if (not cd_canvas) then
    return
  end

  -- do NOT draw the background, use the paper color 

  -- draw the image at the center of the canvas
  local image = canvas.image
  if (image) then
    local margin_width = config:GetVariableDef("Print", "MarginWidth", 20)
    local margin_height = config:GetVariableDef("Print", "MarginHeight", 20)

    local canvas_width, canvas_height, canvas_width_mm, canvas_height_mm = cd_canvas:GetSize()

    -- convert to pixels
    margin_width = math.floor((margin_width * canvas_width) / canvas_width_mm)
    margin_height = math.floor((margin_height * canvas_height) / canvas_height_mm)

    local view_width, view_height = view_fit_rect(
       canvas_width - 2 * margin_width, canvas_height - 2 * margin_height, 
       image:Width(), image:Height())

    local x = math.floor((canvas_width - view_width) / 2)
    local y = math.floor((canvas_height - view_height) / 2)

    image:cdCanvasPutImageRect(cd_canvas, x, y, view_width, view_height, 0, 0, 0, 0)
  end

  cd_canvas:Kill()
end

function item_exit:action()
  local image = canvas.image

  if not save_check(self) then
    return iup.IGNORE  -- to abort the CLOSE_CB callback
  end
  
  if (toolbox.visible == "YES") then
    config:DialogClosed(toolbox, "Toolbox")
    toolbox:hide()
  end

  if (image) then
    image:Destroy()
    canvas.image = nil
  end
  
  config:DialogClosed(iup.GetDialog(self), "MainWindow")
  config:Save()
  config:destroy()
  return iup.CLOSE
end

function item_copy:action()
  local clipboard = iup.clipboard{}
  -- must use iup.SetAttribute because it is an userdata
  iup.SetAttribute(clipboard, "NATIVEIMAGE", iup.GetImageNativeHandle(canvas.image))
  clipboard:destroy()
end

function item_paste:action()
  if save_check(self) then
    local clipboard = iup.clipboard{}
    local image = iup.GetNativeHandleImage(clipboard.nativeimage)
    clipboard:destroy()

    if (not image) then
      show_error("Invalid Clipboard Data", 1)
      return
    end

    set_new_image(canvas, image, nil, "Yes")
  end
end

function item_background:action()
  local colordlg = iup.colordlg{}
  local background = config:GetVariableDef("Canvas", "Background", "255 255 255")
  colordlg.value = background
  colordlg.parentdialog = iup.GetDialog(self)

  colordlg:popup(iup.CENTERPARENT, iup.CENTERPARENT)

  if (tonumber(colordlg.status) == 1) then
    background = colordlg.value
    config:SetVariable("Canvas", "Background", background)

    iup.Update(canvas)
  end

  colordlg:destroy()
end

function item_zoomgrid:action()
  if (self.value == "ON") then
    self.value = "OFF"
  else
    self.value = "ON"
  end
  config:SetVariable("Canvas", "ZoomGrid", self.value)

  iup.Update(canvas)
end

function item_toolbar:action()
  toggle_bar_visibility(self, toolbar)
  config:SetVariable("MainWindow", "Toolbar", item_toolbar.value)
end

function item_toolbox:action()
  if (toolbox.visible == "YES") then
    self.value = "OFF"
    config:DialogClosed(toolbox, "Toolbox")
    iup.Hide(toolbox)
  else
    self.value = "ON"
    config:DialogShow(toolbox, "Toolbox")
  end
  config:SetVariable("MainWindow", "Toolbox", self.value)
end

function item_statusbar:action()
  toggle_bar_visibility(self, statusbar)
  config:SetVariable("MainWindow", "Statusbar", item_statusbar.value)
end

function item_help:action()
  iup.Help("http://www.tecgraf.puc-rio.br/iup")
end

function item_about:action()
  iup.Message("About", "   Simple Paint\n\nAuthors:\n   Gustavo Lyrio\n   Antonio Scuri")
end

function tool_action_cb(ih, state)
  if (state == 1) then
    local tool_index = tonumber(ih.toolindex)
    toolbox.toolindex = tool_index

    if (tool_index == 0) then
      canvas.cursor = "ARROW"
    else
      canvas.cursor = "CROSS"
    end
    if (tool_index == 8) then
      tool_get_text()
    end  
  end
end

function toolcolor_action_cb(self)
  local colordlg = iup.colordlg{}
  local color = self.bgcolor
  colordlg.value = color
  colordlg.parentdialog = iup.GetDialog(self)

  colordlg:popup(iup.CENTER, iup.CENTER)

  if (tonumber(colordlg.status) == 1) then
    color = colordlg.value
    self.bgcolor = color
    toolbox.toolcolor = color    

    iup.Update(canvas)
  end

  colordlg:destroy()
end

function toolwidth_valuechanged_cb(self)
  local value = self.value
  iup.SetAttribute(iup.GetDialog(self), "TOOLWIDTH", value)
end

function toolstyle_valuechanged_cb(self)
  local value = self.value
  iup.SetAttribute(iup.GetDialog(self), "TOOLSTYLE", value)
end

function toolfont_action_cb(self)
  local font_dlg = iup.FontDlg()
  font_dlg.parentdialog = iup.GetDialog(self)
  local font = self.toolfont
  font_dlg.value = font

  font_dlg:Popup(iup.CENTER, iup.CENTER)

  if (font_dlg.status == 1) then
    font = font_dlg.value
    iup.SetAttribute(iup.GetDialog(self), "TOOLFONT", font)
  end
  fond_dlg:destroy()
end

function toolfilltol_valuechanged_cb(self)
  local filltol_label = iup.GetDialogChild(self, "FILLTOLLABEL")
  local value = self.value
  filltol_label.title = "Tol.: "..value.."%"  
  toolbox.toolfilltol = value
end


--********************************** Main (Part 2/2) *****************************************


-- toolbox
gbox = iup.gridbox{
  iup.toggle{toolindex=0, image=load_image_PaintPointer(), value="ON", flat="Yes", tip="Pointer", action = tool_action_cb},
  iup.toggle{toolindex=1, image=load_image_PaintColorPicker(), flat="Yes", tip="Color Picker", action = tool_action_cb},
  iup.toggle{toolindex=2, image=load_image_PaintPencil(), flat="Yes", tip="Pencil", action = tool_action_cb},
  iup.toggle{toolindex=3, image=load_image_PaintLine(), flat="Yes", tip="Line", action = tool_action_cb},
  iup.toggle{toolindex=4, image=load_image_PaintRect(), flat="Yes", tip="Hollow Rectangle", action = tool_action_cb},
  iup.toggle{toolindex=5, image=load_image_PaintBox(), flat="Yes", tip="Box (Filled Rectangle)", action = tool_action_cb},
  iup.toggle{toolindex=6, image=load_image_PaintEllipse(), flat="Yes", tip="Hollow Ellipse", action = tool_action_cb},
  iup.toggle{toolindex=7, image=load_image_PaintOval(), flat="Yes", tip="Oval (Filled Ellipse)", action = tool_action_cb},
  iup.toggle{toolindex=8, image=load_image_PaintText(), flat="Yes", tip="Text", action = tool_action_cb},    
  iup.toggle{toolindex=9, image=load_image_PaintFill(), flat="Yes", tip="Fill Color", action = tool_action_cb},
  gapcol = 2,
  gaplin = 2,
  margin = "5x10",
  numdiv = 2
}

vbox = iup.vbox{
  iup.radio{gbox},
  iup.frame{
    iup.vbox{
      iup.label{title = "Color:", expand="HORIZONTAL"},
      iup.button{name="COLOR", bgcolor="0 0 0", rastersize="28x21", action = toolcolor_action_cb},
      iup.label{title="Width:", expand="HORIZONTAL"},
      iup.text{SPIN="Yes", spinmin=1, rastersize="48x", valuechanged_cb = toolwidth_valuechanged_cb},
      iup.label{title="Style:", expand="HORIZONTAL"},
      iup.list{"____", "----", "....", "-.-.", "-..-..", dropdown="Yes", value=1, valuechanged_cb = toolstyle_valuechanged_cb},
      iup.label{title = "Tol.: 50%", expand="HORIZONTAL", name="FILLTOLLABEL"},
      iup.val{name="FILLTOL", rastersize="60x30", value=50, max=100, valuechanged_cb = toolfilltol_valuechanged_cb},
      iup.label{title="Font:", expand="HORIZONTAL"},
      iup.button{title = "F", name="FONT", rastersize="21x21", font="Times, Bold Italic 11", action = toolfont_action_cb},
      margin="3x2", 
      gap=2, 
      alignment="ACENTER"
    }
  }, 
  nmargin = "2x2",
  aligment = "ACENTER"
}

toolbox = iup.dialog{
  vbox,
  dialogframe = "Yes",
  title = "Tools",
  fontsize = 8,
  toolbox = "Yes",
  -- custom attributes
  toolcolor = "0 0 0",
  toolwidth = 1,
  toolstyle = 1,
  toolfilltol = 50,
  toolindex = 0,
}

--toolbar
btn_new = iup.button{image = "IUP_FileNew", flat = "Yes", action = item_new.action, canfocus="No", tip = "New (Ctrl+N)"}
btn_open = iup.button{image = "IUP_FileOpen", flat = "Yes", action = item_open.action, canfocus="No", tip = "Open (Ctrl+O)"}
btn_save = iup.button{image = "IUP_FileSave", flat = "Yes", action = item_save.action, canfocus="No", tip = "Save (Ctrl+S)"}
btn_copy = iup.button{image =  "IUP_EditCopy", flat = "Yes", action = item_copy.action, canfocus="No", tip = "Copy (Ctrl+C)"}
btn_paste = iup.button{image = "IUP_EditPaste", flat = "Yes", action = item_paste.action, canfocus="No", tip = "Paste (Ctrl+V)"}
btn_zoomgrid = iup.button{image = load_image_PaintZoomGrid(), flat = "Yes", action = item_zoomgrid.action, canfocus="No", tip = "Zoom Grid"}

toolbar = iup.hbox{
  btn_new,
  btn_open,
  btn_save,
  iup.label{separator="VERTICAL"},
  btn_copy,
  btn_paste,
  iup.label{separator="VERTICAL"},
  btn_zoomgrid,
  margin = "5x5",
  gap = 2,
}

function toolbox:close_cb()
  config:DialogClosed(self, "Toolbox")
  item_toolbox.value = "OFF"
  config:SetVariableStr("MainWindow", "Toolbox", "OFF")
end

--statusbar
statusbar = iup.hbox{
  iup.label{title = "(0, 0) = 0   0   0", expand="HORIZONTAL", padding="10x5", name="STATUSLABEL"},
  iup.label{separator="VERTICAL"},
  iup.label{title = "0 x 0", size="70x", padding="10x5", name="SIZELABEL", alignment="ACENTER"},
  iup.label{SEPARATOR="VERTICAL"},
  iup.label{title = "100%", size="30x", padding="10x5", name="ZOOMLABEL", alignment="ARIGHT"},
  iup.button{IMAGE="IUP_ZoomOut", flat="Yes", tip="Zoom Out (Ctrl+-)", action = item_zoomout.action},
  iup.val{value=0, min=-6, max=6, rastersize="150x25", name="ZOOMVAL", valuechanged_cb = zoom_valuechanged_cb},
  iup.button{image="IUP_ZoomIn", flat="Yes", tip="Zoom In (Ctrl++)", action = item_zoomin.action},
  iup.button{image="IUP_ZoomActualSize", flat="Yes", tip="Actual Size (Ctrl+0)", action = item_actualsize.action},
  alignment = "ACENTER",
}

vbox = iup.vbox{
  toolbar,
  canvas,
  statusbar
}

dlg = iup.dialog{
  vbox,
  title = "Simple Paint",
  size = "HALFxHALF",
  menu = menu,
  close_cb = item_exit.action,
  canvas = canvas,
  dropfiles_cb = canvas.dropfiles_cb,
}

-- must be set after dlg was created
toolbox.parentdialog = dlg
toolbox.toolfont = dlg.font

function dlg:move_cb(x, y)
  local old_x = tonumber(self._old_x)
  local old_y = tonumber(self._old_y)
  if (old_x == x and old_y == y) then
    return
  end
  if (toolbox.visible == "YES") then
    local tb_x = tonumber(toolbox.x)
    local tb_y = tonumber(toolbox.y)

    tb_x = tb_x + x - old_x
    tb_y = tb_y + y - old_y

    toolbox:showxy(tb_x, tb_y)
  end

  self._old_x = x
  self._old_y = y
end

function dlg:k_any(c)
  if (c == iup.K_cN) then
    item_new:action()
  elseif (c == iup.K_cO) then
    item_open:action()
  elseif (c == iup.K_cS) then
    item_save:action()
  elseif (c == iup.K_cV) then
    item_paste:action()  
  elseif (c == iup.K_cC) then
    item_copy:action()  
  elseif (c == iup.K_cP) then
    item_print:action()  
  elseif (c == iup.K_cMinus) then
    item_zoomout:action()  
  elseif (c == iup.K_cPlus or c == iup.K_cEqual) then
    item_zoomin:action()  
  elseif (c == iup.K_c0) then
    item_actualsize:action()  
  end
end

-- parent for pre-defined dialogs in closed functions (IupMessage and IupAlarm)
iup.SetGlobal("PARENTDIALOG", iup.SetHandleName(dlg))

-- Initialize variables from the configuration file

config:RecentInit(recent_menu, 10)

local show_zoomgrid = config:GetVariableDef("Canvas", "ZoomGrid", "ON")
if (show_zoomgrid == "OFF") then
  item_zoomgrid.value = "OFF"
end
 
local show_statusbar = config:GetVariableDef("MainWindow", "Statusbar", "ON")
if (show_statusbar == "OFF") then
  item_statusbar.value = "OFF"
  statusbar.floating = "YES"
  statusbar.visible = "NO"
end

local show_toolbar = config:GetVariableDef("MainWindow", "Toolbar", "ON")
if (show_toolbar == "OFF") then
  item_toolbar.value = "OFF"
  toolbar.floating = "YES"
  toolbar.visible = "NO"
end

-- show the dialog at the last position, with the last size
config:DialogShow(dlg, "MainWindow")

local show_toolbox = config:GetVariableDef("MainWindow", "Toolbox", "ON")
if (show_toolbox == "ON") then
    -- configure the very first time to be aligned with the main window
    if (not config:GetVariable("Toolbox", "X")) then
      config:SetVariable("Toolbox", "X", canvas.x)
      config:SetVariable("Toolbox", "Y", canvas.y)
    end
    item_toolbox.value = "ON"
    config:DialogShow(toolbox, "Toolbox")
end

-- open a file from the command line (allow file association in Windows)
if (arg and arg[1]) then
  filename = arg[1]
  open_file(dlg, filename)
end

-- initialize the current file, if not already loaded
check_new_file(dlg)

-- to be able to run this script inside another context
if (iup.MainLoopLevel()==0) then
  iup.MainLoop()
  iup.Close()
end
